package org.dreamwork.tools.network.bridge.client.fx.controllers;

import javafx.fxml.FXML;
import javafx.scene.control.*;
import org.dreamwork.config.KeyValuePair;
import org.dreamwork.network.service.ServiceFactory;
import org.dreamwork.tools.network.bridge.client.data.Proxy;
import org.dreamwork.tools.network.bridge.client.data.Server;
import org.dreamwork.tools.network.bridge.client.services.IClientService;
import org.dreamwork.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

/**
 * Created by seth.yang on 2020/3/9
 */
public class TunnelController extends AbstractController {
    @FXML private Label txtErrorMessage;
    @FXML private TextField txtTunnelName;
    @FXML private ComboBox<String> cmbServers;
    @FXML private Spinner<Integer> spServicePort;
    @FXML private TextField txtLocalServer;
    @FXML private Spinner<Integer> spLocalPort;

    private Proxy proxy;
    private final IClientService service = ServiceFactory.get (IClientService.class);
    private final Logger logger = LoggerFactory.getLogger (TunnelController.class);

    @Override
    public void initialize (URL location, ResourceBundle resources) {
        super.initialize (location, resources);
        List<String> serverNames = new ArrayList<> ();
        background (() -> {
            List<Server> servers = service.getServers ();
            if (servers != null && !servers.isEmpty ()) {
                for (Server server : servers) {
                    serverNames.add (server.getName ());
                }
                post (()-> cmbServers.getItems ().addAll (serverNames));
            }
        });

        spLocalPort.setValueFactory (new SpinnerValueFactory.IntegerSpinnerValueFactory (0, 65535));
        spServicePort.setValueFactory (new SpinnerValueFactory.IntegerSpinnerValueFactory (0, 65535));
    }

    public void setProxy (Proxy proxy) {
        this.proxy = proxy;
        if (proxy != null) {
            bind (proxy);
        }
    }

    private void bind (Proxy proxy) {
        txtTunnelName.setText (proxy.name);
        txtTunnelName.setEditable (false);
        cmbServers.getSelectionModel ().select (proxy.server);
        spServicePort.getValueFactory ().setValue (proxy.servicePort);
        txtLocalServer.setText (proxy.peer);
        spLocalPort.getValueFactory ().setValue (proxy.peerPort);
    }

    private void fill () {
        if (proxy == null) {
            proxy = new Proxy ();
        }


        proxy.name = txtTunnelName.getText ();
        proxy.server = cmbServers.getSelectionModel ().getSelectedItem ();
        proxy.servicePort = spServicePort.getValueFactory ().getValue ();
        proxy.peer = txtLocalServer.getText ();
        proxy.peerPort = spLocalPort.getValueFactory ().getValue ();

        if (logger.isTraceEnabled ()) {
            System.out.println (new com.google.gson.Gson ().toJson (proxy));
        }
    }

    @FXML private void onOkClicked () {
        if (txtTunnelName.isEditable ()) {
            String name = txtTunnelName.getText ();
            if (StringUtil.isEmpty (name)) {
                txtTunnelName.requestFocus ();
                txtErrorMessage.setText (getResource ("err.tunnel.name.missing"));
                return;
            }

            if (service.isProxyPresent (name)) {
                txtTunnelName.requestFocus ();
                txtErrorMessage.setText (getResource ("err.tunnel.exists"));
                return;
            }
        }

        String serverName = cmbServers.getSelectionModel ().getSelectedItem ();
        if (StringUtil.isEmpty (serverName)) {
            cmbServers.requestFocus ();
            txtErrorMessage.setText (getResource ("err.select.server"));
            return;
        }

        int servicePort = spServicePort.getValue ();

        if (service.isProxyPresent (serverName, servicePort)) {
            cmbServers.requestFocus ();
            txtErrorMessage.setText (getResource (
                    "err.tunnel.same.conf",
                    new KeyValuePair<> ("port", servicePort),
                    new KeyValuePair<> ("server", serverName)
            ));
            return;
        }

        String localServer = txtLocalServer.getText ();
        if (StringUtil.isEmpty (localServer)) {
            txtLocalServer.requestFocus ();
            txtErrorMessage.setText (getResource ("err.local.host.missing"));
            return;
        }

        fill ();

        background (()->{
            if (!StringUtil.isEmpty (proxy.id)) {
                service.update (proxy);
            } else {
                proxy.id = StringUtil.uuid ();
                service.save (proxy);
            }

            post (this::cancel);
        });
    }
}